home *** CD-ROM | disk | FTP | other *** search
/ ETO Development Tools 4 / ETO Development Tools 4.iso / Tools - Objects / MacApp / MacApp 3.0a2 / Libraries / UList.cp < prev    next >
Encoding:
Text File  |  1991-05-01  |  55.0 KB  |  1,961 lines  |  [TEXT/MPS ]

  1. // UList.cp 
  2. // Copyright © 1986-1991 by Apple Computer, Inc.  All rights reserved.
  3.  
  4. #ifndef __ULIST__
  5. #include <UList.h>
  6. #endif
  7.  
  8. #ifndef __STDIO__
  9. #include <StdIo.h>
  10. #endif
  11.  
  12. #ifndef __PACKAGES__
  13. #include <Packages.h>
  14. #endif
  15.  
  16. #ifndef __UFAILURE__
  17. #include <UFailure.h>
  18. #endif
  19.  
  20. #ifndef __UMACAPPUTILITIES__
  21. #include <UMacAppUtilities.h>
  22. #endif
  23.  
  24. #ifndef __UITERATOR__
  25. #include <UIterator.h>
  26. #endif
  27.  
  28. //--------------------------------------------------------------------------------------------------
  29. #pragma segment ListRes
  30.  
  31. pascal void TDynamicArray::Initialize(void)        // override 
  32. {
  33.     inherited::Initialize();
  34.  
  35.     fIteratorPtr = NULL;
  36.  
  37.     fAllocatedSize = kEmptyIndex;
  38.     fAllocationIncrement = kAllocationIncrement;// !!! an enhancement would be to support
  39.     // no-growth lists. i.e. fAllocationIncrement
  40.     // of kEmptyIndex. the list would just stay
  41.     // at the size it was allocated and wouldn't
  42.     // shrink and signal failure if an operation
  43.     // needed to grow it
  44.     //!!!fClassSize = this->GetClassSize();
  45.     fElementSize = 1;
  46.     fElementSizeShift = 0;                        //!!!
  47.     fFreeRequested = FALSE;                        // no comment can do this justice 
  48.     fSize = kEmptyIndex;
  49. }
  50.  
  51. //--------------------------------------------------------------------------------------------------
  52. #pragma segment ListRes
  53.  
  54. pascal void TDynamicArray::IDynamicArray(ArrayIndex initialSize,
  55.                                          short elementSize)
  56. {
  57.     this->IObject();
  58.  
  59.     fClassSize = this->GetClassSize();                // Store the class size for use in computeAddress
  60.  
  61.     if (qDebug && (initialSize < kEmptyIndex))
  62.     {
  63.         ProgramBreak("initialSize must be non-negative!");
  64.         initialSize = kEmptyIndex;                //??? Ask programmer 
  65.     }
  66.  
  67.     if (qDebug && (elementSize <= 0))
  68.     {
  69.         ProgramBreak("In TDynamicArray.IDynamicArray: preposterous element size. (zero or negative)");
  70.         Failure(minErr, 0);
  71.     }
  72.  
  73.     fSize = kEmptyIndex;
  74.  
  75.     fElementSize = elementSize;
  76.     fAllocatedSize = kEmptyIndex;
  77.  
  78.     // calculate the elementsizeshift that represents the nearest power of 2 
  79.     fElementSizeShift = 0;
  80.     while (((elementSize - 1) >> fElementSizeShift) > 0)
  81.         ++fElementSizeShift;
  82.  
  83.     this->SetArraySize(initialSize);
  84. }
  85.  
  86. //--------------------------------------------------------------------------------------------------
  87. #pragma segment ListRes
  88.  
  89. pascal void TDynamicArray::DeleteElementsAt(ArrayIndex index,
  90.                                             ArrayIndex count)
  91. {
  92.     const SignedByte initVal = 0xF1;
  93.  
  94.     Ptr indexPtr,  nextElementPtr, lastElementPtr;
  95.     ArrayIndex countBytes;
  96.  
  97.     if (qRangeCheck && ((index < 1) || (index > fSize)))
  98.     {
  99.         fprintf(stderr, "fSize == %1d  index == %1d\n", fSize, index);
  100.         ProgramBreak("Range Check in TDynamicArray.DeleteElementAt");
  101.     }
  102.  
  103.     countBytes = count << fElementSizeShift;
  104.  
  105.     indexPtr = this->ComputeAddress(index);
  106.     nextElementPtr = this->ComputeAddress(index + count);
  107.     lastElementPtr = this->ComputeAddress(fSize + 1);
  108.  
  109.     if (nextElementPtr < lastElementPtr)        // deleted from middle? Compress the array 
  110.         BlockMove(nextElementPtr, indexPtr, (long)lastElementPtr - (long)nextElementPtr);
  111.  
  112.     if (qDebug)
  113.         BlockSet((Ptr)((long)lastElementPtr - countBytes), countBytes, initVal);
  114.  
  115.     this->SetArraySize(fSize - count);            // take up slack if necessary. Should never
  116.                                                 // Fail when shrinking array.
  117.     fSize -= count;
  118.  
  119.     if (fIteratorPtr)                            // Keep all iterations apprised
  120.         fIteratorPtr->DeleteElementAt(index, count);
  121. }
  122.  
  123. //--------------------------------------------------------------------------------------------------
  124. #pragma segment ListRes
  125.  
  126. pascal void TDynamicArray::GetElementsAt(ArrayIndex index,
  127.                                          void* ElementPtr,
  128.                                          ArrayIndex count)
  129. {
  130.     if (qRangeCheck && ((index < 1) || (index > fSize)))
  131.     {
  132.         fprintf(stderr, "fSize == %1d  index == %1d\n", fSize, index);
  133.         ProgramBreak("Range Check in TDynamicArray.ReplaceElementAt");
  134.     }
  135.     // The count computation for this blockmove makes sure that if the element size is not
  136.     // a power of 2 that we don't copy more bytes back to the caller than required for a
  137.     // given number of elements… sending the caller into orbit and heading straight for the Excedrin.
  138.  
  139.     // !!! NOTE MULTIPLE (> 1) element moves for non-power of 2 element sizes are not yet supported!
  140.  
  141.     if (count > kEmptyIndex)
  142.         BlockMove(this->ComputeAddress(index), (Ptr)ElementPtr, ((count - 1) << fElementSizeShift) + fElementSize);
  143. }
  144.  
  145. //--------------------------------------------------------------------------------------------------
  146. #pragma segment ListRes
  147. // if qTrace Called _FREQUENTLY_ 
  148.  
  149. pascal Ptr TDynamicArray::ComputeAddress(ArrayIndex index)
  150. {
  151. #if FALSE
  152.     // This is the ideal situation.  Unfortunately it is too slow for something as
  153.     // widely used as Dynamic Arrays, so we break the encapsulation below.  If your subclass
  154.     // wishes to manage storage gotten from somewhere other than the object's handle then
  155.     // you must override GetDynamicPtr to return a pointer to the storage to be managed and
  156.     // ALSO override ComputeAddress to use this commented out code.
  157.     Ptr p;
  158.  
  159.     p = this->GetDynamicPtr();
  160.     if (qDebug && !p)
  161.         DebugStr("ComputeAddress called with an empty list (no dynamic area allocated)");
  162.  
  163.     // p + ((index - 1) * fElementSize) 
  164.     return (Ptr)((long)p + (((index - 1)) << fElementSizeShift));
  165. #endif
  166.  
  167.     // Break encapsulation and just return an index off of this which we know to be a handle MacApp 2.0
  168.     return (Ptr)(StripLong(*((Handle)this)) + fClassSize + ((index - 1) << fElementSizeShift));
  169. }
  170.  
  171. //--------------------------------------------------------------------------------------------------
  172. #pragma segment ListRes
  173.  
  174. pascal void TDynamicArray::Free(void)
  175. {
  176.     // She can't do it cap'n. The dilithium crystals are burrrrnt out! If they're
  177.     // allowed to rest a while they might recover enough for another try.
  178.     if (fIteratorPtr)
  179.     {
  180.         fFreeRequested = TRUE;
  181.         // Release our dynamic portion now, but wait to be freed 
  182.         if (fSize > kEmptyIndex)
  183.             this->DeleteElementsAt(1, fSize);
  184.     }
  185.     else
  186.         inherited::Free();
  187. }
  188.  
  189. //--------------------------------------------------------------------------------------------------
  190. #pragma segment ListRes
  191.  
  192. pascal ArrayIndex TDynamicArray::GetSize(void)
  193. {
  194.     return fSize;
  195. }
  196.  
  197. //--------------------------------------------------------------------------------------------------
  198. #pragma segment ListRes
  199.  
  200. pascal void TDynamicArray::InsertElementsBefore(ArrayIndex index,
  201.                                                 void* ElementPtr,
  202.                                                 ArrayIndex count)
  203. {
  204.     Ptr indexPtr,  nextIndexPtr, lastElementPtr;
  205.     ArrayIndex countBytes;
  206.  
  207.     if (qRangeCheck && ((index < 1) || (index > fSize + 1)))
  208.     {
  209.         fprintf(stderr, "fSize == %1d  index == %1d\n", fSize, index);
  210.         ProgramBreak("Range Check in TDynamicArray.InsertBefore");
  211.     }
  212.  
  213.     this->SetArraySize(fSize + count);                // make sure there's room if needed 
  214.  
  215.     indexPtr = this->ComputeAddress(index);
  216.     nextIndexPtr = this->ComputeAddress(index + count);
  217.     lastElementPtr = this->ComputeAddress(fSize + 1);
  218.     countBytes = count << fElementSizeShift;
  219.  
  220.     if (index <= fSize)                            // clear out a hole? 
  221.         BlockMove(indexPtr, nextIndexPtr, (long)lastElementPtr - (long)indexPtr);
  222.  
  223.     // !!! we still don't account for multiple element moves with non power of 2 element sizes.
  224.     // Would it be best to create a MoveElements method and put the smarts in it?
  225.  
  226.     if ((countBytes == sizeof(long)) &&!odd((Ptr)ElementPtr) &&!odd(indexPtr))
  227.         *((long*)indexPtr) = *((long*)ElementPtr);// shortcut for longs 
  228.     else
  229.         BlockMove((Ptr)ElementPtr, indexPtr, countBytes);// longcut for shorts (and other sizes) 
  230.  
  231.     fSize += count;
  232.  
  233.     if (fIteratorPtr)                            // Keep all iterations apprised
  234.         fIteratorPtr->InsertElementBefore(index, count);
  235. }
  236.  
  237. //--------------------------------------------------------------------------------------------------
  238. #pragma segment ListRes
  239.  
  240. pascal Boolean TDynamicArray::IsEmpty(void)
  241. {
  242.     return (fSize == kEmptyIndex);
  243. }
  244.  
  245. //--------------------------------------------------------------------------------------------------
  246. #pragma segment ListRes
  247.  
  248. // DON'T use exit to get out of this routine from your TestElement function or you will be really
  249. // sad!  (our debugger will check for you) That's why you can return TRUE to stop enumerating.
  250. // Signaling Failure is OK too.
  251. pascal ArrayIndex TDynamicArray::EachElementDoTil(TestIndexType TestElement,
  252.                                                   void* staticLink,
  253.                                                   Boolean IterateForward)
  254. {
  255.     return this->EachElementInRangeDoTil(1, fSize, TestElement, staticLink, IterateForward);
  256. }
  257.  
  258. //--------------------------------------------------------------------------------------------------
  259. #pragma segment ListRes
  260.  
  261. // DON'T use exit to get out of this routine from your TestElement function or you will be really
  262. // sad!  (our debugger will check for you) That's why you can return TRUE to stop enumerating.
  263. // Signaling Failure is OK too.
  264. pascal ArrayIndex TDynamicArray::EachElementInRangeDoTil(ArrayIndex lowBound,
  265.                                                          ArrayIndex highBound,
  266.                                                          TestIndexType TestElement,
  267.                                                          void* staticLink,
  268.                                                          Boolean IterateForward)
  269. {
  270.     // Can't even special case one element lists, wouldn't be sure of index to return if the
  271.     // TestElement call inserted or deleted.
  272.     if (fSize > kEmptyIndex)
  273.     {
  274.         CArrayIterator iter(this, lowBound, highBound, IterateForward);
  275.         
  276.         for (ArrayIndex i = iter.FirstIndex(); iter.More(); i = iter.NextIndex())
  277.         {
  278.             if (TestElement(i, staticLink))
  279.                 return i;
  280.         }
  281.     }
  282.     return kEmptyIndex;
  283. }
  284.  
  285. //--------------------------------------------------------------------------------------------------
  286. #pragma segment ListRes
  287.  
  288. pascal void TDynamicArray::Merge(TDynamicArray* aDynamicArray)
  289. {
  290.     if (qDebug && ((fElementSize != aDynamicArray->fElementSize) || (fElementSizeShift != aDynamicArray->fElementSizeShift)))
  291.         ProgramBreak("In TDynamicArray->Merge: fElementSize or fElementSizeShift don't match with the TDynamicArray to merge!");
  292.  
  293.     if (aDynamicArray->GetSize() != kEmptyIndex)
  294.         this->InsertElementsBefore(this->GetSize() + 1, aDynamicArray->ComputeAddress(1), aDynamicArray->GetSize());
  295. }
  296.  
  297. //--------------------------------------------------------------------------------------------------
  298. #pragma segment ListRes
  299.  
  300. pascal void TDynamicArray::ReplaceElementsAt(ArrayIndex index,
  301.                                              void* ElementPtr,
  302.                                              ArrayIndex count)
  303. {
  304.     if (qRangeCheck && ((index < 1) || (index > fSize)))
  305.     {
  306.         fprintf(stderr, "fSize == %1d  index == %1d\n", fSize, index);
  307.         ProgramBreak("Range Check in TDynamicArray.ReplaceElementAt");
  308.     }
  309.     BlockMove((Ptr)ElementPtr, this->ComputeAddress(index), count << fElementSizeShift);
  310. }
  311.  
  312. //--------------------------------------------------------------------------------------------------
  313. #pragma segment ListRes
  314.  
  315. pascal void TDynamicArray::SetArraySize(ArrayIndex theSize)
  316. {
  317.     ArrayIndex newAllocatedSize;
  318.  
  319.     if ((theSize > fAllocatedSize) || (fAllocatedSize - theSize >= fAllocationIncrement))
  320.     {
  321.         if (qDebug && (fAllocationIncrement < 0))
  322.             ProgramBreak("fAllocationIncrement < 0 !  You have serious problems.");
  323.  
  324.         // Set the # of allocated elements to the nearest multiple of fAllocationIncrement.
  325.         // Wait until after the SetDynamicSize to set fAllocatedSize in case SetDynamicSize
  326.         // signals failure.
  327.         if (fAllocationIncrement)
  328.             newAllocatedSize = (theSize + fAllocationIncrement) - (theSize + fAllocationIncrement) % fAllocationIncrement;
  329.         else
  330.             newAllocatedSize = theSize;
  331.  
  332.         if (newAllocatedSize != fAllocatedSize)
  333.             this->SetDynamicSize(newAllocatedSize << fElementSizeShift);
  334.  
  335.         fAllocatedSize = newAllocatedSize;
  336.     }
  337. }
  338.  
  339. //--------------------------------------------------------------------------------------------------
  340. #pragma segment MAFields
  341.  
  342. pascal void TDynamicArray::Fields(TObject* obj)    // override 
  343. {
  344.     obj->DoToField("TDynamicArray", (Ptr)NULL, bClass);
  345.     obj->DoToField("fIteratorPtr", (Ptr) & fIteratorPtr, bPointer);
  346.     obj->DoToField("fSize", (Ptr) & fSize, bLongInt);
  347.     obj->DoToField("fElementSize", (Ptr) & fElementSize, bInteger);
  348.     obj->DoToField("fElementSizeShift", (Ptr) & fElementSizeShift, bInteger);
  349.     obj->DoToField("fAllocationIncrement", (Ptr) & fAllocationIncrement, bLongInt);
  350.     obj->DoToField("fAllocatedSize", (Ptr) & fAllocatedSize, bLongInt);
  351.     obj->DoToField("fFreeRequested", (Ptr) & fFreeRequested, bBoolean);
  352.     obj->DoToField("fClassSize", (Ptr) & fClassSize, bLongInt);
  353.  
  354.     inherited::Fields(obj);
  355. }
  356.  
  357. //--------------------------------------------------------------------------------------------------
  358. #pragma segment MAFields
  359. pascal void TDynamicArray::DynamicFields(TObject* obj)// override 
  360. {
  361.     obj->DoToField("Dynamic Fields", NULL, bTitle);
  362.  
  363.     CArrayIterator iter(this);
  364.     
  365.     for (ArrayIndex i = iter.FirstIndex(); iter.More(); i = iter.NextIndex())
  366.     {
  367.         Str255 aString;
  368.     
  369.         NumToString(i, aString);
  370.         aString = ".At[" + aString + "]";
  371.         obj->DoToField(aString, this->ComputeAddress(i), bPointer);
  372.     }
  373. }
  374.  
  375. //--------------------------------------------------------------------------------------------------
  376. #pragma segment ListRes
  377.  
  378. pascal void TSortedDynamicArray::ISortedDynamicArray(ArrayIndex initialSize,
  379.                                                      short elementSize)
  380. {
  381.     this->IDynamicArray(initialSize, elementSize);
  382. }
  383.  
  384. //--------------------------------------------------------------------------------------------------
  385. #pragma segment ListRes
  386.  
  387. pascal CompareResult TSortedDynamicArray::CompareElements(void* ,
  388.                                                           void*)
  389. {
  390.     // By Default consider all items equal 
  391.     return kItem1EqualItem2;
  392. }
  393.  
  394. //--------------------------------------------------------------------------------------------------
  395. #pragma segment ListRes
  396.  
  397. // DON'T use exit to get out of this routine from your TestItem function or you will be really
  398. // sad!  (our debugger will check for you) That's why you can return TRUE to stop enumerating.
  399. // Signaling Failure is OK too.
  400. pascal Boolean TSortedDynamicArray::DoSearchElement(CompareIndexType TestItem,
  401.                                                     void* staticLink,
  402.                                                     ArrayIndex& index)
  403. {
  404.     Boolean found = FALSE;
  405.  
  406.     if (fSize == kEmptyIndex)
  407.         index = 1;
  408.     else
  409.     {
  410.         CompareResult aCompareResult;
  411.         CArrayIterator iter(this);
  412.  
  413.         do
  414.         {
  415.             // (fLowBound + fHighBound) / 2
  416.             iter.fCurrentIndex = (iter.fLowBound + iter.fHighBound) >> 1;
  417.  
  418.             aCompareResult = TestItem(iter.fCurrentIndex, staticLink);
  419.  
  420.             if (aCompareResult <= kItemGreaterThanCriteria)
  421.                 iter.fHighBound = iter.fCurrentIndex - 1;
  422.             else
  423.                 iter.fLowBound = iter.fCurrentIndex + 1;
  424.  
  425.         } while (!((aCompareResult == kItemEqualCriteria) || (iter.fLowBound > iter.fHighBound)));
  426.  
  427.         if (aCompareResult == kItemEqualCriteria)
  428.             found = TRUE;
  429.         else if (aCompareResult >= kItemLessThanCriteria)
  430.             ++iter.fCurrentIndex;
  431.  
  432.         // keep index in range 
  433.         if ((iter.fCurrentIndex < 1) || (iter.fCurrentIndex > fSize + 1))
  434.             index = kEmptyIndex;
  435.         else
  436.             index = iter.fCurrentIndex;
  437.  
  438.     }
  439.     return found;
  440. }
  441.  
  442. //--------------------------------------------------------------------------------------------------
  443. #pragma segment ListRes
  444.  
  445. class CElementInserter
  446. {
  447.     void*& fElementPtr;
  448.     TSortedDynamicArray* fDynamicArray;
  449.  
  450. public:
  451.     CElementInserter(void*& theElementPtr,
  452.                      TSortedDynamicArray* theDynamicArray) :
  453.         fElementPtr(theElementPtr),
  454.         fDynamicArray(theDynamicArray)
  455.     {
  456.     }
  457.  
  458.     pascal CompareResult TestItem(ArrayIndex anItem);
  459.  
  460. };
  461.  
  462. #pragma segment ListRes
  463. pascal CompareResult CElementInserter::TestItem(ArrayIndex anItem)
  464. {
  465.     return fDynamicArray->CompareElements(fElementPtr, fDynamicArray->ComputeAddress(anItem));
  466. }
  467.  
  468. #pragma segment ListRes
  469. pascal void TSortedDynamicArray::InsertElementInOrder(void* elementPtr)
  470. {
  471.     ArrayIndex index;
  472.     CElementInserter anElementInserter(elementPtr, this);
  473.  
  474.     this->DoSearchElement((CompareIndexType) & CElementInserter::TestItem, &anElementInserter, index);
  475.     this->InsertElementsBefore(index, elementPtr, 1);
  476. }
  477.  
  478. //--------------------------------------------------------------------------------------------------
  479. #pragma segment MAFields
  480.  
  481. pascal void TSortedDynamicArray::Fields(TObject* obj)// override 
  482. {
  483.     obj->DoToField("TSortedDynamicArray", (Ptr)NULL, bClass);
  484.  
  485.     inherited::Fields(obj);
  486. }
  487.  
  488. //--------------------------------------------------------------------------------------------------
  489. #pragma segment ListRes
  490.  
  491. pascal TList* NewList(void)
  492. {
  493.     TList * list;
  494.  
  495.     list = new TList;
  496.     list->IList();
  497.     return list;
  498. }
  499.  
  500. //--------------------------------------------------------------------------------------------------
  501. #pragma segment ListRes
  502.  
  503. pascal TSortedList* NewSortedList(void)
  504. {
  505.     TSortedList * list;
  506.  
  507.  
  508.     list = new TSortedList;
  509.     list->ISortedList();
  510.     return list;
  511. }
  512.  
  513. //--------------------------------------------------------------------------------------------------
  514. #pragma segment ListRes
  515.  
  516. pascal TList* NewAllocatedList(ArrayIndex iSize)
  517. {
  518.     TList * list;
  519.  
  520.     list = NewList();
  521.     list->SetArraySize(iSize);
  522.     return list;
  523. }
  524.  
  525. //--------------------------------------------------------------------------------------------------
  526. #pragma segment ListRes
  527.  
  528. pascal TSortedList* FreeListIfObject(TSortedList* list)
  529. {
  530.     if (list)
  531.     {
  532.         if (qDebug)
  533.             FailNonObject(list);
  534.  
  535.         list->FreeList();
  536.     }
  537.     return (TSortedList *)NULL;
  538. }
  539.  
  540. //--------------------------------------------------------------------------------------------------
  541. #pragma segment ListRes
  542.  
  543. pascal void TSortedList::Initialize(void)        // override 
  544. {
  545.     inherited::Initialize();
  546.  
  547.     fObjClassID = kNilClass;
  548. }
  549.  
  550. //--------------------------------------------------------------------------------------------------
  551. #pragma segment ListRes
  552.  
  553. // Default comparison is identity 
  554. pascal CompareResult TSortedList::Compare(TObject* item1,
  555.                                           TObject* item2)
  556. {
  557.     if (item1 > item2)
  558.         return kItem1GreaterThanItem2;
  559.     else if (item1 < item2)
  560.         return kItem1LessThanItem2;
  561.     else
  562.         return kItem1EqualItem2;
  563. }
  564.  
  565. //--------------------------------------------------------------------------------------------------
  566. #pragma segment ListRes
  567.  
  568. pascal CompareResult TSortedList::CompareElements(void* element1,
  569.                                                   void* element2)// override 
  570. {
  571.     return this->Compare(*((TObjectPtrPtr)element1), *((TObjectPtrPtr)element2));
  572. }
  573.  
  574. //--------------------------------------------------------------------------------------------------
  575. #pragma segment ListRes
  576.  
  577. pascal void TSortedList::ISortedList(void)
  578. {
  579.     // Can't do sizeof(TObject) because sizeof
  580.     // returns the record size for objects
  581.     this->ISortedDynamicArray(kEmptyIndex, sizeof(Handle));
  582. }
  583.  
  584. //--------------------------------------------------------------------------------------------------
  585. #pragma segment ListRes
  586.  
  587. class CSearchIndex
  588. {
  589.     CompareObjectType& fTestItem;
  590.     void*& fStaticLink;
  591.     TObject*& fObject;
  592.     TSortedList* fSortedList;
  593.  
  594. public:
  595.     // Constructor
  596.     CSearchIndex(CompareObjectType& TestItem,
  597.                  void*& staticLink,
  598.                  TObject*& theObject,
  599.                  TSortedList* theSortedList) :
  600.         fTestItem(TestItem),
  601.         fStaticLink(staticLink),
  602.         fObject(theObject),
  603.         fSortedList(theSortedList)
  604.     {
  605.     }
  606.  
  607.     pascal CompareResult TestElement(ArrayIndex anItem);
  608. };
  609.  
  610. #pragma segment ListRes
  611. pascal CompareResult CSearchIndex::TestElement(ArrayIndex anItem)
  612. {
  613.     fObject = *((TObjectPtrPtr)fSortedList->ComputeAddress(anItem));// in case the index is deleted by the test. 
  614.     if (qDebug)
  615.         FailNonObject(fObject);
  616.     return fTestItem(fObject, fStaticLink);
  617. }
  618.  
  619. #pragma segment ListRes
  620. // DON'T use exit to get out of this routine from your TestItem function or you will be really
  621. // sad!  (our debugger will check for you).
  622. pascal TObject* TSortedList::DoSearch(CompareObjectType TestItem,
  623.                                       void* staticLink,
  624.                                       ArrayIndex& index)
  625. {
  626.     TObject * obj;
  627.     CSearchIndex aSearcher(TestItem, staticLink, obj, this);
  628.  
  629.     if (this->DoSearchElement((CompareIndexType) & CSearchIndex::TestElement, &aSearcher, index))
  630.         return obj;
  631.     else
  632.         return NULL;
  633. }
  634.  
  635. //--------------------------------------------------------------------------------------------------
  636. #pragma segment ListRes
  637.  
  638. class CObjectComparer
  639. {
  640.     TObject*& fObject;
  641.     TSortedList* fSortedList;
  642.  
  643. public:
  644.     // Constructor
  645.     CObjectComparer(TObject*& theObject,
  646.                     TSortedList* theSortedList) :
  647.         fObject(theObject),
  648.         fSortedList(theSortedList)
  649.     {
  650.     }
  651.  
  652.     // if qTrace
  653.     pascal CompareResult CompareObjects(TObject* anItem);
  654. };
  655.  
  656. #pragma segment ListRes
  657. pascal CompareResult CObjectComparer::CompareObjects(TObject* anItem)
  658. {
  659.     if (qDebug)
  660.         FailNonObject(anItem);
  661.     return fSortedList->Compare(fObject, anItem);
  662. }
  663.  
  664. #pragma segment ListRes
  665. pascal ArrayIndex TSortedList::GetEqualItemNo(TObject* item)
  666. {
  667.     ArrayIndex index;
  668.     CObjectComparer anObjectComparer(item, this);
  669.  
  670.     if (qDebug)
  671.         FailNonObject(item);
  672.     if (this->DoSearch((CompareObjectType) & CObjectComparer::CompareObjects, &anObjectComparer, index))
  673.         return index;
  674.     else
  675.         return kEmptyIndex;
  676. }
  677.  
  678. //--------------------------------------------------------------------------------------------------
  679. #pragma segment ListRes
  680.  
  681. pascal void TSortedList::Insert(TObject* item)
  682. {
  683.     if (qDebug)
  684.         FailNonObject(item);
  685.  
  686.     this->InsertElementInOrder(&item);
  687. }
  688.  
  689. //--------------------------------------------------------------------------------------------------
  690. #pragma segment ListRes
  691. pascal void TSortedList::QuickSort(ArrayIndex beginIndex,
  692.                                    ArrayIndex endIndex,
  693.                                    CompareObjectsType CompareItems,
  694.                                    void* staticLink)
  695. {
  696.     TObject * pivot = NULL;
  697.     TObject * firstKey;
  698.     TObject * secondKey;
  699.     ArrayIndex left = beginIndex;
  700.     ArrayIndex right = endIndex;
  701.  
  702.     // Find the pivot value
  703.     firstKey = this->At(beginIndex);
  704.     for (ArrayIndex index = beginIndex + 1; index <= endIndex; ++index)// Scan for a different key
  705.     {
  706.         secondKey = this->At(index);
  707.         short compareResults;
  708.  
  709.         if ((compareResults = CompareItems(secondKey, firstKey, staticLink)) >= kItem1GreaterThanItem2)
  710.         {
  711.             pivot = secondKey;
  712.             break;
  713.         }
  714.         else if (compareResults <= kItem1LessThanItem2)
  715.         {
  716.             pivot = firstKey;
  717.             break;
  718.         }
  719.     }
  720.  
  721.     if (pivot)                                    // Don't do anything if the objects are all equal
  722.     {
  723.         do
  724.         {
  725.             TObject * leftObject = this->At(left);
  726.             TObject * rightObject = this->At(right);
  727.  
  728.             // Swap the elements
  729.             this->ReplaceElementsAt(left, &rightObject, 1);
  730.             this->ReplaceElementsAt(right, &leftObject, 1);
  731.  
  732.             // now the scan phase begins
  733.             while (CompareItems(this->At(left), pivot, staticLink) <= kItem1LessThanItem2)
  734.                 ++left;
  735.             while (CompareItems(this->At(right), pivot, staticLink) >= kItem1EqualItem2)
  736.                 --right;
  737.         } while (left <= right);
  738.  
  739.         this->QuickSort(beginIndex, left - 1, CompareItems, staticLink);
  740.         this->QuickSort(left, endIndex, CompareItems, staticLink);
  741.     }
  742. }
  743.  
  744. //--------------------------------------------------------------------------------------------------
  745. #pragma segment ListRes
  746.  
  747. // if qTrace
  748. pascal CompareResult CompareObjects(TObject* item1,
  749.                                     TObject* item2,
  750.                                     void* staticLink)
  751. {
  752.     return ((TSortedList *)staticLink)->Compare(item1, item2);
  753. }
  754.  
  755.  
  756. pascal void TSortedList::Sort(void)
  757. {
  758.     this->QuickSort(1, fSize, CompareObjects, this);
  759. }
  760.  
  761. //--------------------------------------------------------------------------------------------------
  762. #pragma segment ListRes
  763.  
  764. //!!! Sort would be nice to have at the TDynamicArray level too…  Parameterized types where are you?
  765. // NOTE: This doesn't work with a CompareItems Function that inserts or deletes elements.
  766. pascal void TSortedList::SortBy(CompareObjectsType CompareItems,
  767.                                 void* staticLink)
  768. {
  769.     this->QuickSort(1, fSize, CompareItems, staticLink);
  770. }
  771.  
  772. //--------------------------------------------------------------------------------------------------
  773. #pragma segment ListRes
  774.  
  775. pascal TObject* TSortedList::Search(CompareObjectType TestItem,
  776.                                     void* staticLink)
  777. {
  778.     ArrayIndex index;
  779.  
  780.     return this->DoSearch(TestItem, staticLink, index);
  781. }
  782.  
  783. //--------------------------------------------------------------------------------------------------
  784. #pragma segment MAFields
  785.  
  786. pascal void TSortedList::Fields(TObject* obj)    // override 
  787. {
  788.     MAName aString;
  789.  
  790.     obj->DoToField("TSortedList", (Ptr)NULL, bClass);
  791.     GetClassNameFromID(fObjClassID, aString);
  792.     obj->DoToField("fObjClassID", (Ptr) & aString, bString);
  793.     inherited::Fields(obj);
  794. }
  795.  
  796. //--------------------------------------------------------------------------------------------------
  797. #pragma segment MAInspector
  798.  
  799. pascal void TSortedList::GetInspectorName(Str255& inspectorName)// override 
  800. {
  801.     if (fObjClassID != kNilClass)
  802.     {
  803.         GetClassNameFromID(fObjClassID, inspectorName);
  804.         inspectorName = "Of " + inspectorName + " Size: ";
  805.         ConcatNumber(inspectorName, this->GetSize(), inspectorName);
  806.     }
  807. }
  808.  
  809. //--------------------------------------------------------------------------------------------------
  810. #pragma segment ListRes
  811.  
  812. pascal TObject* TSortedList::At(ArrayIndex index)
  813. {
  814.     if (qRangeCheck && ((index <= kEmptyIndex) || (index > fSize)))
  815.     {
  816.         fprintf(stderr, "fSize == %1d  index == %1d\n", fSize, index);
  817.         ProgramBreak("Range Check in TList.At");
  818.     }
  819.  
  820.     return *((TObjectPtrPtr)ComputeAddress(index));
  821. }
  822.  
  823. //--------------------------------------------------------------------------------------------------
  824. #pragma segment ListRes
  825.  
  826. pascal void TSortedList::AtDelete(ArrayIndex index)
  827. {
  828.     if (qRangeCheck && ((index <= kEmptyIndex) || (index > fSize)))
  829.     {
  830.         fprintf(stderr, "fSize == %1d  index == %1d\n", fSize, index);
  831.         ProgramBreak("Range Check in TList.AtDelete");
  832.     }
  833.  
  834.     this->DeleteElementsAt(index, 1);
  835. }
  836.  
  837. //--------------------------------------------------------------------------------------------------
  838. #pragma segment ListRes
  839.  
  840. pascal void TSortedList::Delete(TObject* item)
  841. {
  842.     ArrayIndex index;
  843.  
  844.     if (qDebug)
  845.         FailNonObject(item);
  846.     index = this->GetIdentityItemNo(item);
  847.     if (index != kEmptyIndex)
  848.         this->AtDelete(index);
  849. }
  850.  
  851. //--------------------------------------------------------------------------------------------------
  852. #pragma segment ListRes
  853.  
  854. pascal void TSortedList::DeleteAll(void)
  855. {
  856.     if (fSize > kEmptyIndex)
  857.         this->DeleteElementsAt(1, fSize);
  858. }
  859.  
  860. //--------------------------------------------------------------------------------------------------
  861. #pragma segment ListRes
  862. pascal void TSortedList::Each(DoToObjectType DoToItem,
  863.                               void* staticLink)
  864. {
  865.     CObjectIterator iter(this);
  866.     
  867.     for (TObject* obj = iter.FirstObject(); iter.More(); obj = iter.NextObject())
  868.         DoToItem(obj, staticLink);
  869. }
  870.  
  871.  
  872.  
  873. //--------------------------------------------------------------------------------------------------
  874. #pragma segment ListRes
  875.  
  876. pascal TObject* TSortedList::First(void)
  877. {
  878.     if (fSize <= kEmptyIndex)
  879.         return NULL;
  880.     else
  881.         return this->At(1);
  882. }
  883.  
  884. //--------------------------------------------------------------------------------------------------
  885. #pragma segment ListRes
  886.  
  887. pascal TObject* TSortedList::FirstThat(TestObjectType TestItem,
  888.                                        void* staticLink)
  889. {
  890.     ArrayIndex index;
  891.  
  892.     return this->IterateTil(TestItem, staticLink, kIterateForward, index);
  893. }
  894.  
  895. //--------------------------------------------------------------------------------------------------
  896. #pragma segment ListRes
  897. pascal void TSortedList::FreeAll(void)
  898. {
  899.     CObjectIterator iter(this);
  900.  
  901.     for (TObject* obj = iter.FirstObject(); iter.More(); obj = iter.NextObject())
  902.         FreeIfObject(obj);
  903.  
  904.     this->DeleteAll();
  905. }
  906.  
  907. //--------------------------------------------------------------------------------------------------
  908. #pragma segment ListRes
  909.  
  910. pascal void TSortedList::FreeList(void)
  911. {
  912.     this->FreeAll();
  913.     this->Free();
  914. }
  915.  
  916. //--------------------------------------------------------------------------------------------------
  917. // Search for the identity item. The list may ordered by some other
  918. // means than identity thus we must do a linear search to find the
  919. // requested item
  920. pascal ArrayIndex TSortedList::GetIdentityItemNo(TObject* item)
  921. {
  922.     if (qDebug)
  923.         FailNonObject(item);
  924.         
  925.     // the equality test should not change the list's size or the resulting index can be invalid 
  926.     CArrayIterator iter(this);
  927.  
  928.     for (ArrayIndex i = iter.FirstIndex(); iter.More(); i = iter.NextIndex())
  929.         if (this->At(i) == item)
  930.             return i;
  931.     return kEmptyIndex;
  932. }
  933.  
  934. //--------------------------------------------------------------------------------------------------
  935. #pragma segment MAFields
  936. pascal void TSortedList::DynamicFields(TObject* obj)// override 
  937. {
  938.     obj->DoToField("Dynamic Fields", (Ptr)NULL, bTitle);
  939.  
  940.     CArrayIterator iter(this);
  941.     
  942.     for (ArrayIndex i = iter.FirstIndex(); iter.More(); i = iter.NextIndex())
  943.     {
  944.         Str255 aString;
  945.     
  946.         NumToString(i, aString);
  947.         aString = ".At[" + aString + "]";
  948.         obj->DoToField(aString, this->ComputeAddress(i), bObject);
  949.     }
  950. }
  951.  
  952. //--------------------------------------------------------------------------------------------------
  953. #pragma segment ListRes
  954. pascal TObject* TSortedList::IterateTil(TestObjectType TestItem,
  955.                                         void* staticLink,
  956.                                         Boolean IterateForward,
  957.                                         ArrayIndex& itsIndex)
  958. {
  959.     CArrayIterator iter(this, IterateForward);
  960.     
  961.     for (itsIndex = iter.FirstIndex(); iter.More(); itsIndex = iter.NextIndex())
  962.     {
  963.         TObject * testObject = this->At(itsIndex);
  964.         if (TestItem(testObject, staticLink))
  965.             return testObject;
  966.     }
  967.  
  968.     return NULL;
  969. }
  970.  
  971. //--------------------------------------------------------------------------------------------------
  972. #pragma segment ListRes
  973.  
  974. pascal TObject* TSortedList::Last(void)
  975. {
  976.     if (fSize <= kEmptyIndex)
  977.         return NULL;
  978.     else
  979.         return this->At(fSize);
  980. }
  981.  
  982. //--------------------------------------------------------------------------------------------------
  983. #pragma segment ListRes
  984.  
  985. pascal TObject* TSortedList::LastThat(TestObjectType TestItem,
  986.                                       void* staticLink)
  987. {
  988.     ArrayIndex index;
  989.  
  990.     return this->IterateTil(TestItem, staticLink, kIterateBackward, index);
  991. }
  992.  
  993. //--------------------------------------------------------------------------------------------------
  994. #pragma segment ListDebug
  995.  
  996. pascal void TSortedList::SetEltType(const MAName& toClass)
  997. {
  998.     MAName s;
  999.  
  1000.     // Forgive the caller for calling this twice only if the same type was specified both times 
  1001.     if (qDebug && (fObjClassID != kNilClass))
  1002.     {
  1003.         GetClassNameFromID(fObjClassID, s);
  1004.         if (toClass != s)
  1005.         {
  1006.             fprintf(stderr, "The list already contains %s; trying to change to %s\n",
  1007.                     (char *) s, (char *) toClass);
  1008.             ProgramBreak("In TList.SetEltType");
  1009.         }
  1010.     }
  1011.     // Assign the field 
  1012.     fObjClassID = GetClassIDFromName(toClass);    // srf 88.9.7 
  1013. }
  1014.  
  1015. //-------------------------------------------------------------------------------------------------
  1016. #pragma segment ListDebug
  1017.  
  1018. pascal void TSortedList::SetEltTypeID(ObjClassID toClassID)
  1019. {
  1020.     MAName s,  newClassName;
  1021.  
  1022.     // Forgive the caller for calling this twice only if the same type was specified both times 
  1023.     if (qDebug && (fObjClassID != kNilClass))
  1024.     {
  1025.         if (fObjClassID != toClassID)
  1026.         {
  1027.             GetClassNameFromID(fObjClassID, s);
  1028.             GetClassNameFromID(toClassID, newClassName);
  1029.             fprintf(stderr, "The list already contains %s; trying to change to %s\n",
  1030.                     (char *) s, (char *) newClassName);
  1031.             ProgramBreak("In TList.SetEltTypeID");
  1032.         }
  1033.     }
  1034.     // Assign the field 
  1035.     fObjClassID = toClassID;
  1036. }
  1037.  
  1038. //--------------------------------------------------------------------------------------------------
  1039. #pragma segment ListRes
  1040.  
  1041. pascal void TList::IList(void)
  1042. {
  1043.     this->ISortedList();
  1044. }
  1045.  
  1046. //--------------------------------------------------------------------------------------------------
  1047. #pragma segment ListRes
  1048.  
  1049. pascal void TList::AtPut(ArrayIndex index,
  1050.                          TObject* newItem)
  1051. {
  1052.     if (qRangeCheck && ((index <= kEmptyIndex) || (index > fSize)))
  1053.     {
  1054.         fprintf(stderr, "fSize == %1d  index == %1d\n", fSize, index);
  1055.         ProgramBreak("Range Check in TList.AtPut");
  1056.         // Can't continue, bad index trashes memory ??? Would it be nice to
  1057.         // have a mechanism where the developer could supply a new index here?
  1058.         Failure(minErr, 0);
  1059.     }
  1060.  
  1061.     if (qDebug)
  1062.     {
  1063.         FailNonObject(newItem);
  1064.         if (fObjClassID != kNilClass)
  1065.             if (!IsMemberClassID(newItem, fObjClassID))
  1066.             {
  1067.                 fprintf(stderr, "newItem: %p\n", newItem);
  1068.                 ProgramBreak("In TList.AtPut: inserting invalid object type");
  1069.             }
  1070.     }
  1071.     *((TObjectPtrPtr)ComputeAddress(index)) = newItem;
  1072. }
  1073.  
  1074. //--------------------------------------------------------------------------------------------------
  1075. #pragma segment ListRes
  1076. // DON'T use exit to get out of this routine from your TestItem function or you will be really
  1077. // sad!  (our debugger will check for you) That's why you can return TRUE to stop enumerating.
  1078. // Signaling Failure is OK too.
  1079. pascal Boolean TList::DoSearchElement(CompareIndexType TestItem,
  1080.                                       void* staticLink,
  1081.                                       ArrayIndex& index)// override 
  1082. {
  1083.     CArrayIterator iter(this);
  1084.     
  1085.     for (index = iter.FirstIndex(); iter.More(); index = iter.NextIndex())
  1086.         if (TestItem(index, staticLink) == kItem1EqualItem2)
  1087.             return TRUE;
  1088.  
  1089.     index = fSize + 1;
  1090.     return FALSE;
  1091. }
  1092.  
  1093. //--------------------------------------------------------------------------------------------------
  1094. #pragma segment ListRes
  1095.  
  1096. // Overridden to do arrival sequence insertion 
  1097. pascal void TList::InsertElementInOrder(void* ElementPtr)// override 
  1098. {
  1099.     this->InsertElementsBefore(fSize + 1, ElementPtr, 1);
  1100. }
  1101.  
  1102. //--------------------------------------------------------------------------------------------------
  1103. #pragma segment ListRes
  1104.  
  1105. pascal void TList::InsertBefore(ArrayIndex index,
  1106.                                 TObject* item)
  1107. {
  1108.     if (qRangeCheck && ((index <= kEmptyIndex) || (index > fSize + 1)))
  1109.     {
  1110.         fprintf(stderr, "fSize == %1d  index == %1d\n", fSize, index);
  1111.         ProgramBreak("Range Check in TList.InsertBefore");
  1112.     }
  1113.  
  1114.     if (qDebug)
  1115.     {
  1116.         FailNonObject(item);
  1117.         if (fObjClassID != kNilClass)
  1118.             if (!IsMemberClassID(item, fObjClassID))
  1119.             {
  1120.                 fprintf(stderr, "item: %p\n", item);
  1121.                 ProgramBreak("In TList.InsertBefore: inserting invalid object type");
  1122.             }
  1123.     }
  1124.     this->InsertElementsBefore(index, &item, 1);
  1125. }
  1126.  
  1127. //--------------------------------------------------------------------------------------------------
  1128. #pragma segment ListRes
  1129.  
  1130. pascal void TList::InsertFirst(TObject* item)
  1131. {
  1132.     // Depend on InsertBefore for sanity checking 
  1133.     this->InsertBefore(1, item);
  1134. }
  1135.  
  1136. //--------------------------------------------------------------------------------------------------
  1137.  
  1138. pascal void TList::InsertLast(TObject* item)
  1139. {
  1140.     // Depend on InsertBefore for sanity checking 
  1141.     this->InsertBefore(fSize + 1, item);
  1142. }
  1143.  
  1144. //--------------------------------------------------------------------------------------------------
  1145. #pragma segment MAFields
  1146.  
  1147. pascal void TList::Fields(TObject* obj)            // override 
  1148.  
  1149. {
  1150.     obj->DoToField("TList", (Ptr)NULL, bClass);
  1151.     inherited::Fields(obj);
  1152. }
  1153.  
  1154. //--------------------------------------------------------------------------------------------------
  1155. #pragma segment ListRes
  1156.  
  1157. pascal void TList::Push(TObject* item)
  1158. {
  1159.     // Depend on InsertBefore for sanity checking 
  1160.     this->InsertLast(item);
  1161. }
  1162.  
  1163. //--------------------------------------------------------------------------------------------------
  1164. #pragma segment ListRes
  1165.  
  1166. pascal TObject* TList::Pop(void)
  1167. {
  1168.     TObject * topOfStack;
  1169.  
  1170.     if (fSize == kEmptyIndex)
  1171.         topOfStack = NULL;
  1172.     else
  1173.     {
  1174.         topOfStack = this->At(fSize);
  1175.         this->AtDelete(fSize);
  1176.     }
  1177.     return topOfStack;
  1178. }
  1179.  
  1180. //--------------------------------------------------------------------------------------------------
  1181. #pragma segment ListRes
  1182.  
  1183. pascal void TList::Queue(TObject* item)
  1184. {
  1185.     // Depend on InsertBefore for sanity checking 
  1186.     this->InsertLast(item);
  1187. }
  1188.  
  1189. //--------------------------------------------------------------------------------------------------
  1190. #pragma segment ListRes
  1191.  
  1192. pascal TObject* TList::Dequeue(void)
  1193. {
  1194.     TObject * beginningOfStack;
  1195.  
  1196.     if (fSize <= kEmptyIndex)
  1197.         beginningOfStack = NULL;
  1198.     else
  1199.     {
  1200.         beginningOfStack = this->At(1);
  1201.         this->AtDelete(1);
  1202.     }
  1203.     return beginningOfStack;
  1204. }
  1205.  
  1206. //--------------------------------------------------------------------------------------------------
  1207. #pragma segment ListRes
  1208.  
  1209. pascal void THandleList::IHandleList(void)
  1210. {
  1211.     // Initialize a new list with no elements, i.e., fSize == 0 
  1212.     this->ISortedDynamicArray(kEmptyIndex, sizeof(Handle));
  1213. }
  1214.  
  1215. //--------------------------------------------------------------------------------------------------
  1216. #pragma segment ListRes
  1217.  
  1218. // Return the index'th element of the list. 
  1219. pascal Handle THandleList::At(ArrayIndex index)
  1220. {
  1221.     if (qRangeCheck && ((index < 1) || (index > fSize)))
  1222.     {
  1223.         fprintf(stderr, "fSize == %1d  index == %1d\n", fSize, index);
  1224.         ProgramBreak("Range Check in THandleList.At");
  1225.     }
  1226.  
  1227.     return *((HandlePtr)ComputeAddress(index));
  1228. }
  1229.  
  1230. //--------------------------------------------------------------------------------------------------
  1231. #pragma segment ListRes
  1232.  
  1233. // Deletes via an index. 
  1234. pascal void THandleList::AtDelete(ArrayIndex index)
  1235. {
  1236.     if (qRangeCheck && ((index < 1) || (index > fSize)))
  1237.     {
  1238.         fprintf(stderr, "fSize == %1d  index == %1d\n", fSize, index);
  1239.         ProgramBreak("Range Check in THandleList.AtDelete");
  1240.     }
  1241.     this->DeleteElementsAt(index, 1);
  1242. }
  1243.  
  1244. //--------------------------------------------------------------------------------------------------
  1245. #pragma segment ListRes
  1246.  
  1247. pascal void THandleList::Delete(Handle item)
  1248. {
  1249.     ArrayIndex index;
  1250.  
  1251.     index = this->GetIdentityItemNo(item);
  1252.     if (index != kEmptyIndex)
  1253.         this->AtDelete(index);
  1254. }
  1255.  
  1256. //--------------------------------------------------------------------------------------------------
  1257. #pragma segment ListRes
  1258.  
  1259. pascal void THandleList::DeleteAll(void)
  1260. {
  1261.     if (fSize > kEmptyIndex)
  1262.         this->DeleteElementsAt(1, fSize);
  1263. }
  1264.  
  1265. //--------------------------------------------------------------------------------------------------
  1266. #pragma segment ListRes
  1267.  
  1268. class CSearchHandleIndex
  1269. {
  1270.     CompareHandleType& fTestItem;
  1271.     void*& fStaticLink;
  1272.     Handle& fHandle;
  1273.     THandleList* fHandleList;
  1274.  
  1275. public:
  1276.     // Constructor
  1277.     CSearchHandleIndex(CompareHandleType& TestItem,
  1278.                        void*& staticLink,
  1279.                        Handle& theHandle,
  1280.                        THandleList* theHandleList) :
  1281.         fTestItem(TestItem),
  1282.         fStaticLink(staticLink),
  1283.         fHandle(theHandle),
  1284.         fHandleList(theHandleList)
  1285.     {
  1286.     }
  1287.  
  1288.     pascal CompareResult TestElement(ArrayIndex anItem);
  1289. };
  1290.  
  1291. #pragma segment ListRes
  1292. pascal CompareResult CSearchHandleIndex::TestElement(ArrayIndex anItem)
  1293. {
  1294.     fHandle = fHandleList->At(anItem);
  1295.     return fTestItem(fHandle, fStaticLink);
  1296. }
  1297.  
  1298. #pragma segment ListRes
  1299. // DON'T use exit to get out of this routine from your TestItem function or you will be really
  1300. // sad!  (our debugger will check for you).
  1301. pascal Handle THandleList::DoSearch(CompareHandleType TestItem,
  1302.                                     void* staticLink,
  1303.                                     ArrayIndex& index)
  1304. {
  1305.     Handle aHandle = NULL;
  1306.     CSearchHandleIndex aSearcher(TestItem, staticLink, aHandle, this);
  1307.  
  1308.     if (this->DoSearchElement((CompareIndexType) & CSearchHandleIndex::TestElement, &aSearcher, index))
  1309.         return aHandle;
  1310.     else
  1311.         return NULL;
  1312. }
  1313.  
  1314. //--------------------------------------------------------------------------------------------------
  1315. #pragma segment ListRes
  1316. pascal void THandleList::Each(DoToHandleType DoToItem,
  1317.                               void* staticLink)
  1318. {
  1319.     CHandleIterator iter(this);
  1320.     
  1321.     for (Handle aHandle = iter.FirstHandle(); iter.More(); aHandle = iter.NextHandle())
  1322.         DoToItem(aHandle, staticLink);
  1323. }
  1324.  
  1325. //--------------------------------------------------------------------------------------------------
  1326. #pragma segment ListRes
  1327.  
  1328. // Return the first element of the list.
  1329. pascal Handle THandleList::First(void)
  1330. {
  1331.     if (fSize <= kEmptyIndex)
  1332.         return NULL;
  1333.     else
  1334.         return this->At(1);
  1335. }
  1336.  
  1337. //--------------------------------------------------------------------------------------------------
  1338. #pragma segment ListRes
  1339.  
  1340. // Call DoToItem once for each element of the list, in order. 
  1341. pascal Handle THandleList::FirstThat(TestHandleType TestItem,
  1342.                                      void* staticLink)
  1343. {
  1344.     ArrayIndex index;
  1345.  
  1346.     return this->IterateTil(TestItem, staticLink, kIterateForward, index);
  1347. }
  1348.  
  1349. //--------------------------------------------------------------------------------------------------
  1350. #pragma segment ListRes
  1351.  
  1352. pascal Boolean EqualHandles(Handle listItem,
  1353.                             void* staticLink)
  1354. {
  1355.     if (listItem == (Handle)staticLink)
  1356.         return TRUE;
  1357.     else
  1358.         return FALSE;
  1359. }
  1360.  
  1361. // Find the first reference to the IDENTITY item in the list.
  1362. // If item does not occur, return 0.
  1363. pascal ArrayIndex THandleList::GetIdentityItemNo(Handle item)
  1364. {
  1365.     ArrayIndex index;
  1366.  
  1367.     this->IterateTil(EqualHandles, item, kIterateForward, index);
  1368.     return index;
  1369. }
  1370.  
  1371. //--------------------------------------------------------------------------------------------------
  1372. #pragma segment ListRes
  1373.  
  1374. class CHandleComparer
  1375. {
  1376.     Handle& fHandle;
  1377.     THandleList* fHandleList;
  1378.  
  1379. public:
  1380.     // Constructor
  1381.     CHandleComparer(Handle& theHandle,
  1382.                     THandleList* theHandleList) :
  1383.         fHandle(theHandle),
  1384.         fHandleList(theHandleList)
  1385.     {
  1386.     }
  1387.  
  1388.     // if qTrace
  1389.     pascal CompareResult CompareHandles(Handle anItem);
  1390. };
  1391.  
  1392. #pragma segment ListRes
  1393. pascal CompareResult CHandleComparer::CompareHandles(Handle anItem)
  1394. {
  1395.     return fHandleList->Compare(fHandle, anItem);
  1396. }
  1397.  
  1398. #pragma segment ListRes
  1399. // Find the first reference to item in the list.
  1400. // If item does not occur, return 0.
  1401. pascal ArrayIndex THandleList::GetEqualItemNo(Handle item)
  1402. {
  1403.     ArrayIndex index;
  1404.     CHandleComparer aHandleComparer(item, this);
  1405.  
  1406.     if (this->DoSearch((CompareHandleType) & CHandleComparer::CompareHandles, &aHandleComparer, index))
  1407.         return index;
  1408.     else
  1409.         return kEmptyIndex;
  1410. }
  1411.  
  1412. //--------------------------------------------------------------------------------------------------
  1413. #pragma segment ListRes
  1414.  
  1415. pascal void THandleList::Insert(Handle item)
  1416. {
  1417.     this->InsertElementInOrder(&item);
  1418. }
  1419.  
  1420. //--------------------------------------------------------------------------------------------------
  1421. #pragma segment ListRes
  1422.  
  1423. // By default just compare the ordinal value of the items.  Subclasses that want to use the items
  1424. // as pointers or other types should override if the comparison is based on the pointed at value
  1425. pascal CompareResult THandleList::Compare(Handle item1,
  1426.                                           Handle item2)
  1427. {
  1428.     if (item1 > item2)
  1429.         return kItem1GreaterThanItem2;
  1430.     else if (item1 < item2)
  1431.         return kItem1LessThanItem2;
  1432.     else
  1433.         return kItem1EqualItem2;
  1434. }
  1435.  
  1436. //--------------------------------------------------------------------------------------------------
  1437. #pragma segment ListRes
  1438.  
  1439. pascal CompareResult THandleList::CompareElements(void* element1,
  1440.                                                   void* element2)// override 
  1441. {
  1442.     return this->Compare(*((HandlePtr)element1), *((HandlePtr)element2));
  1443. }
  1444.  
  1445. //--------------------------------------------------------------------------------------------------
  1446. #pragma segment ListRes
  1447. pascal Handle THandleList::IterateTil(TestHandleType TestItem,
  1448.                                       void* staticLink,
  1449.                                       Boolean IterateForward,
  1450.                                       ArrayIndex& itsIndex)
  1451. {
  1452.     CArrayIterator iter(this, IterateForward);
  1453.     
  1454.     for (itsIndex = iter.FirstIndex(); iter.More(); itsIndex = iter.NextIndex())
  1455.     {
  1456.         Handle testHandle = this->At(itsIndex);
  1457.         if (TestItem(testHandle, staticLink))
  1458.             return testHandle;
  1459.     }
  1460.  
  1461.     return NULL;
  1462. }
  1463.  
  1464. //--------------------------------------------------------------------------------------------------
  1465. #pragma segment ListRes
  1466.  
  1467. // Return the last element of the list.
  1468. pascal Handle THandleList::Last(void)
  1469. {
  1470.     if (fSize <= kEmptyIndex)
  1471.         return NULL;
  1472.     else
  1473.         return this->At(fSize);
  1474. }
  1475.  
  1476. //--------------------------------------------------------------------------------------------------
  1477. #pragma segment ListRes
  1478.  
  1479. // Call DoToItem once for each element of the list, in order. 
  1480. pascal Handle THandleList::LastThat(TestHandleType TestItem,
  1481.                                     void* staticLink)
  1482. {
  1483.     ArrayIndex index;
  1484.  
  1485.     return this->IterateTil(TestItem, staticLink, kIterateBackward, index);
  1486. }
  1487.  
  1488. //--------------------------------------------------------------------------------------------------
  1489. #pragma segment MAFields
  1490.  
  1491. pascal void THandleList::Fields(TObject* obj)    // override 
  1492. {
  1493.     obj->DoToField("THandleList", (Ptr)NULL, bClass);
  1494.     inherited::Fields(obj);
  1495. }
  1496.  
  1497. //--------------------------------------------------------------------------------------------------
  1498. #pragma segment MAFields
  1499. pascal void THandleList::DynamicFields(TObject* obj)// override 
  1500. {
  1501.     obj->DoToField("Dynamic Fields", (Ptr)NULL, bTitle);
  1502.  
  1503.     CArrayIterator iter(this);
  1504.  
  1505.     for (ArrayIndex i = iter.FirstIndex(); iter.More(); i = iter.NextIndex())
  1506.     {
  1507.         Str255 aString;
  1508.     
  1509.         NumToString(i, aString);
  1510.         aString = ".At[" + aString + "]";
  1511.         obj->DoToField(aString, this->ComputeAddress(i), bHandle);
  1512.     }
  1513. }
  1514.  
  1515. //--------------------------------------------------------------------------------------------------
  1516. #pragma segment ListRes
  1517.  
  1518. pascal void TSortedLongintList::ISortedLongintList(void)
  1519. {
  1520.     // Initialize a new list with no elements, i.e., fSize == 0 
  1521.     this->ISortedDynamicArray(kEmptyIndex, sizeof(long));
  1522. }
  1523.  
  1524. //--------------------------------------------------------------------------------------------------
  1525. #pragma segment ListRes
  1526.  
  1527. // Return the index'th element of the list. 
  1528. pascal long TSortedLongintList::At(ArrayIndex index)
  1529. {
  1530.     if (qRangeCheck && ((index < 1) || (index > fSize)))
  1531.     {
  1532.         fprintf(stderr, "fSize == %1d  index == %1d\n", fSize, index);
  1533.         ProgramBreak("Range Check in TSortedLongintList.At");
  1534.     }
  1535.  
  1536.     return *((LongIntPtr)ComputeAddress(index));
  1537. }
  1538.  
  1539. //--------------------------------------------------------------------------------------------------
  1540. #pragma segment ListRes
  1541.  
  1542. // Deletes via an index. 
  1543. pascal void TSortedLongintList::AtDelete(ArrayIndex index)
  1544. {
  1545.     if (qRangeCheck && ((index < 1) || (index > fSize)))
  1546.     {
  1547.         fprintf(stderr, "fSize == %1d  index == %1d\n", fSize, index);
  1548.         ProgramBreak("Range Check in TSortedLongintList.AtDelete");
  1549.     }
  1550.  
  1551.     this->DeleteElementsAt(index, 1);
  1552. }
  1553.  
  1554. //--------------------------------------------------------------------------------------------------
  1555. #pragma segment ListRes
  1556.  
  1557. pascal void TSortedLongintList::Delete(long item)
  1558. {
  1559.     ArrayIndex index;
  1560.  
  1561.     index = this->GetIdentityItemNo(item);
  1562.     if (index != kEmptyIndex)
  1563.         this->AtDelete(index);
  1564. }
  1565.  
  1566. //--------------------------------------------------------------------------------------------------
  1567. #pragma segment ListRes
  1568.  
  1569. pascal void TSortedLongintList::DeleteAll(void)
  1570. {
  1571.     if (fSize > kEmptyIndex)
  1572.         this->DeleteElementsAt(1, fSize);
  1573. }
  1574.  
  1575. //--------------------------------------------------------------------------------------------------
  1576. #pragma segment ListRes
  1577. pascal void TSortedLongintList::Each(DoToLongType DoToItem,
  1578.                                      void* staticLink)
  1579. {
  1580.     CLongintIterator iter(this);
  1581.  
  1582.     for (long aLong = iter.FirstLong(); iter.More(); aLong = iter.NextLong())
  1583.         DoToItem(aLong, staticLink);
  1584. }
  1585.  
  1586. //--------------------------------------------------------------------------------------------------
  1587. #pragma segment ListRes
  1588.  
  1589. // Return the first element of the list.
  1590. pascal long TSortedLongintList::First(void)
  1591. {
  1592.     if (fSize <= kEmptyIndex)
  1593.         return 0;
  1594.     else
  1595.         return this->At(1);
  1596. }
  1597.  
  1598. //--------------------------------------------------------------------------------------------------
  1599. #pragma segment ListRes
  1600.  
  1601. // Call DoToItem once for each element of the list, in order. 
  1602. pascal long TSortedLongintList::FirstThat(TestLongType TestItem,
  1603.                                           void* staticLink)
  1604. {
  1605.     ArrayIndex index;
  1606.  
  1607.     return this->IterateTil(TestItem, staticLink, kIterateForward, index);
  1608. }
  1609.  
  1610. //--------------------------------------------------------------------------------------------------
  1611. #pragma segment ListRes
  1612.  
  1613. pascal Boolean TestItem(long listItem,
  1614.                         void* staticLink)
  1615. {
  1616.     if (listItem == *((LongIntPtr)staticLink))
  1617.         return TRUE;
  1618.     else
  1619.         return FALSE;
  1620. }
  1621.  
  1622. // Find the first reference to the IDENTITY item in the list.
  1623. // If item does not occur, return 0.
  1624. pascal ArrayIndex TSortedLongintList::GetIdentityItemNo(long item)
  1625. {
  1626.     ArrayIndex index;
  1627.  
  1628.     this->IterateTil(TestItem, &item, kIterateForward, index);
  1629.     return index;
  1630. }
  1631.  
  1632. //--------------------------------------------------------------------------------------------------
  1633. #pragma segment ListRes
  1634. pascal long TSortedLongintList::IterateTil(TestLongType TestItem,
  1635.                                            void* staticLink,
  1636.                                            Boolean IterateForward,
  1637.                                            ArrayIndex& itsIndex)
  1638. {
  1639.     CArrayIterator iter(this, IterateForward);
  1640.     
  1641.     for (itsIndex = iter.FirstIndex(); iter.More(); itsIndex = iter.NextIndex())
  1642.     {
  1643.         long testLong = this->At(itsIndex);
  1644.         if (TestItem(testLong, staticLink))
  1645.             return testLong;
  1646.     }
  1647.  
  1648.     return 0;
  1649. }
  1650.  
  1651. //--------------------------------------------------------------------------------------------------
  1652. #pragma segment ListRes
  1653.  
  1654. // Return the last element of the list.
  1655. pascal long TSortedLongintList::Last(void)
  1656. {
  1657.     if (fSize <= kEmptyIndex)
  1658.         return 0;
  1659.     else
  1660.         return this->At(fSize);
  1661. }
  1662.  
  1663. //--------------------------------------------------------------------------------------------------
  1664. #pragma segment ListRes
  1665.  
  1666. // Call DoToItem once for each element of the list, in order. 
  1667. pascal long TSortedLongintList::LastThat(TestLongType TestItem,
  1668.                                          void* staticLink)
  1669. {
  1670.     ArrayIndex index;
  1671.  
  1672.     return this->IterateTil(TestItem, staticLink, kIterateBackward, index);
  1673. }
  1674.  
  1675. //--------------------------------------------------------------------------------------------------
  1676. #pragma segment ListRes
  1677.  
  1678. // By default just compare the ordinal value of the items.  Subclasses that want to use the items
  1679. // as pointers or other types should override if the comparison is based on the pointed at value
  1680. pascal CompareResult TSortedLongintList::Compare(long item1,
  1681.                                                  long item2)
  1682. {
  1683.     if (item1 > item2)
  1684.         return kItem1GreaterThanItem2;
  1685.     else if (item1 < item2)
  1686.         return kItem1LessThanItem2;
  1687.     else
  1688.         return kItem1EqualItem2;
  1689. }
  1690.  
  1691. //--------------------------------------------------------------------------------------------------
  1692. #pragma segment ListRes
  1693.  
  1694. pascal CompareResult TSortedLongintList::CompareElements(void* element1,
  1695.                                                          void* element2)// override 
  1696. {
  1697.     return this->Compare(*((LongIntPtr)element1), *((LongIntPtr)element2));
  1698. }
  1699.  
  1700. //--------------------------------------------------------------------------------------------------
  1701. #pragma segment ListRes
  1702.  
  1703. class CSearchLongIndex
  1704. {
  1705.     CompareLongType& fTestItem;
  1706.     void*& fStaticLink;
  1707.     long& fLong;
  1708.     TSortedLongintList* fLongintList;
  1709.  
  1710. public:
  1711.     // Constructor
  1712.     CSearchLongIndex(CompareLongType& TestItem,
  1713.                      void*& staticLink,
  1714.                      long& theLong,
  1715.                      TSortedLongintList* theLongintList) :
  1716.         fTestItem(TestItem),
  1717.         fStaticLink(staticLink),
  1718.         fLong(theLong),
  1719.         fLongintList(theLongintList)
  1720.     {
  1721.     }
  1722.  
  1723.     pascal CompareResult TestElement(ArrayIndex anItem);
  1724. };
  1725.  
  1726. #pragma segment ListRes
  1727. pascal CompareResult CSearchLongIndex::TestElement(ArrayIndex anItem)
  1728. {
  1729.     fLong = fLongintList->At(anItem);
  1730.     return fTestItem(fLong, fStaticLink);
  1731. }
  1732.  
  1733. #pragma segment ListRes
  1734. // DON'T use exit to get out of this routine from your TestItem function or you will be really
  1735. // sad!  (our debugger will check for you).
  1736. pascal long TSortedLongintList::DoSearch(CompareLongType TestItem,
  1737.                                          void* staticLink,
  1738.                                          ArrayIndex& index)
  1739. {
  1740.     long aLong = NULL;
  1741.     CSearchLongIndex aSearcher(TestItem, staticLink, aLong, this);
  1742.  
  1743.     if (this->DoSearchElement((CompareIndexType) & CSearchLongIndex::TestElement, &aSearcher, index))
  1744.         return aLong;
  1745.     else
  1746.         return NULL;
  1747. }
  1748.  
  1749. //--------------------------------------------------------------------------------------------------
  1750. #pragma segment ListRes
  1751.  
  1752. class CLongComparer
  1753. {
  1754.     long& fLong;
  1755.     TSortedLongintList* fSortedLongintList;
  1756.  
  1757. public:
  1758.     // Constructor
  1759.     CLongComparer(long& theLong,
  1760.                   TSortedLongintList* theSortedLongintList) :
  1761.         fLong(theLong),
  1762.         fSortedLongintList(theSortedLongintList)
  1763.     {
  1764.     }
  1765.  
  1766.     // if qTrace
  1767.     pascal CompareResult CompareLongs(long anItem);
  1768. };
  1769.  
  1770. #pragma segment ListRes
  1771. pascal CompareResult CLongComparer::CompareLongs(long anItem)
  1772. {
  1773.     return fSortedLongintList->Compare(fLong, anItem);
  1774. }
  1775.  
  1776. #pragma segment ListRes
  1777. // Find the first reference to item in the list.
  1778. // If item does not occur, return 0.
  1779. pascal ArrayIndex TSortedLongintList::GetEqualItemNo(long item)
  1780. {
  1781.     ArrayIndex index;
  1782.     CLongComparer aLongComparer(item, this);
  1783.  
  1784.     if (this->DoSearch((CompareLongType) & CLongComparer::CompareLongs, &aLongComparer, index))
  1785.         return index;
  1786.     else
  1787.         return kEmptyIndex;
  1788. }
  1789.  
  1790. //--------------------------------------------------------------------------------------------------
  1791. #pragma segment ListRes
  1792.  
  1793. pascal void TSortedLongintList::Insert(long item)
  1794. {
  1795.     this->InsertElementInOrder(&item);
  1796. }
  1797.  
  1798. //--------------------------------------------------------------------------------------------------
  1799. #pragma segment ListRes
  1800.  
  1801. pascal long TSortedLongintList::Search(CompareLongType TestItem,
  1802.                                        void* staticLink)
  1803. {
  1804.     ArrayIndex index;
  1805.  
  1806.     return this->DoSearch(TestItem, staticLink, index);
  1807. }
  1808.  
  1809. //--------------------------------------------------------------------------------------------------
  1810. #pragma segment MAFields
  1811.  
  1812. pascal void TSortedLongintList::Fields(TObject* obj)// override 
  1813. {
  1814.     obj->DoToField("TSortedLongintList", (Ptr)NULL, bClass);
  1815.     inherited::Fields(obj);
  1816. }
  1817.  
  1818. //--------------------------------------------------------------------------------------------------
  1819. #pragma segment MAFields
  1820. pascal void TSortedLongintList::DynamicFields(TObject* obj)// override 
  1821. {
  1822.     obj->DoToField("Dynamic Fields", (Ptr)NULL, bTitle);
  1823.  
  1824.     CArrayIterator iter(this);
  1825.  
  1826.     for (ArrayIndex i = iter.FirstIndex(); iter.More(); i = iter.NextIndex())
  1827.     {
  1828.         Str255 aString;
  1829.     
  1830.         NumToString(i, aString);
  1831.         aString = ".At[" + aString + "]";
  1832.         obj->DoToField(aString, this->ComputeAddress(i), bLongInt);
  1833.     }
  1834. }
  1835.  
  1836. //--------------------------------------------------------------------------------------------------
  1837. #pragma segment ListRes
  1838.  
  1839. pascal void TLongintList::ILongintList(void)
  1840. {
  1841.     // Initialize a new list with no elements, i.e., fSize == 0 
  1842.     this->ISortedLongintList();
  1843. }
  1844.  
  1845. //--------------------------------------------------------------------------------------------------
  1846. #pragma segment ListRes
  1847.  
  1848. // DON'T use exit to get out of this routine from your TestItem function or you will be really
  1849. // sad!  (our debugger will check for you) That's why you can return TRUE to stop enumerating.
  1850. // Signaling Failure is OK too.
  1851. pascal Boolean TLongintList::DoSearchElement(CompareIndexType TestItem,
  1852.                                              void* staticLink,
  1853.                                              ArrayIndex& index)// override 
  1854. {
  1855.     CArrayIterator iter(this);
  1856.     
  1857.     for (index = iter.FirstIndex(); iter.More(); index = iter.NextIndex())
  1858.         if (TestItem(index, staticLink) == kItem1EqualItem2)
  1859.             return TRUE;
  1860.  
  1861.     index = fSize + 1;
  1862.     return FALSE;
  1863. }
  1864.  
  1865. //--------------------------------------------------------------------------------------------------
  1866. #pragma segment ListRes
  1867.  
  1868. // Overridden to do arrival sequence insertion 
  1869. pascal void TLongintList::InsertElementInOrder(void* ElementPtr)// override 
  1870. {
  1871.     this->InsertElementsBefore(fSize + 1, ElementPtr, 1);
  1872. }
  1873.  
  1874. //--------------------------------------------------------------------------------------------------
  1875. #pragma segment ListRes
  1876.  
  1877. // Replace the index'th element of the list.
  1878. // Range check only if the compile-flag qRangeCheck is TRUE.
  1879. pascal void TLongintList::AtPut(ArrayIndex index,
  1880.                                 long newItem)
  1881. {
  1882.     if (qRangeCheck && ((index < 1) || (index > fSize)))
  1883.     {
  1884.         fprintf(stderr, "fSize == %1d  index == %1d\n", fSize, index);
  1885.         ProgramBreak("Range Check in TLongintList.AtPut");
  1886.     }
  1887.  
  1888.     *((LongIntPtr)ComputeAddress(index)) = newItem;
  1889. }
  1890.  
  1891. //--------------------------------------------------------------------------------------------------
  1892. #pragma segment ListRes
  1893.  
  1894. // Insert a reference to item at the indicated index.
  1895. pascal void TLongintList::InsertBefore(ArrayIndex index,
  1896.                                        long item)
  1897. {
  1898.     if (qRangeCheck && ((index < 1) || (index > fSize + 1)))
  1899.     {
  1900.         fprintf(stderr, "fSize == %1d  index == %1d\n", fSize, index);
  1901.         ProgramBreak("Range Check in TLongintList.InsertBefore");
  1902.     }
  1903.  
  1904.     this->InsertElementsBefore(index, &item, 1);
  1905. }
  1906.  
  1907. //--------------------------------------------------------------------------------------------------
  1908. #pragma segment ListRes
  1909.  
  1910. // Insert a reference to item at the front of the list.
  1911. pascal void TLongintList::InsertFirst(long item)
  1912. {
  1913.     this->InsertBefore(1, item);
  1914. }
  1915.  
  1916. //--------------------------------------------------------------------------------------------------
  1917.  
  1918. // Insert a reference to item at the back of the list.
  1919. pascal void TLongintList::InsertLast(long item)
  1920. {
  1921.     this->InsertBefore(fSize + 1, item);
  1922. }
  1923.  
  1924. //--------------------------------------------------------------------------------------------------
  1925. #pragma segment MAFields
  1926.  
  1927. pascal void TLongintList::Fields(TObject* obj)    // override 
  1928. {
  1929.     obj->DoToField("TLongintList", (Ptr)NULL, bClass);
  1930.     inherited::Fields(obj);
  1931. }
  1932.  
  1933. //--------------------------------------------------------------------------------------------------
  1934. #pragma segment ListRes
  1935.  
  1936. // LIFO stack push. 
  1937. pascal void TLongintList::Push(long item)
  1938. {
  1939.     this->InsertLast(item);
  1940. }
  1941.  
  1942. //--------------------------------------------------------------------------------------------------
  1943. #pragma segment ListRes
  1944.  
  1945. // LIFO stack pop 
  1946. pascal long TLongintList::Pop(void)
  1947. {
  1948.     long topOfStack;
  1949.  
  1950.     if (fSize == kEmptyIndex)
  1951.         topOfStack = 0;
  1952.     else
  1953.     {
  1954.         topOfStack = this->At(fSize);
  1955.         this->AtDelete(fSize);
  1956.     }
  1957.     return topOfStack;
  1958. }
  1959.  
  1960.  
  1961.